#include "TSS_Memery.h"

//从指定地址偏移一定的长度，进行数据读写
#define MEM_MOVE_8(p, size) *((volatile uint8_t *)p + (size))
#define MEM_MOVE_16(p, size) *((volatile uint16_t *)p + (size) / 2)
#define MEM_MOVE_32(p, size) *((volatile uint32_t *)p + (size) / 4)
//偏移的重要地址
#define MEM_SIZE() MEM_MOVE_16(mem, 0)                      //内存大小
#define MEM_NUM() MEM_MOVE_16(mem, 2)                       //数据个数
#define MEM_LEN(n) MEM_MOVE_16(mem, MEM_SIZE() - 2 - 2 * n) //第n个数据的宽度

//计算两个数据之间的偏移量
static uint16_t MEM_OFFSET(void *mem, uint16_t n1, uint16_t n2)
{
    uint16_t offset = 0;
    for (uint16_t i = n1; i < n2; i++)
    {
        offset += MEM_LEN(i);
    }
    return offset;
}
//查找第n个数据的地址
static void *MEM_DATA(void *mem, uint16_t n)
{
    if (n > MEM_NUM())
        return NULL;
    uint16_t offset = MEM_OFFSET(mem, 0, n);
    return (void *)&MEM_MOVE_8(mem, 4 + offset);
}
//返回列表剩余空间
static int16_t MEM_SPACE(void *mem)
{
    uint16_t offset = MEM_OFFSET(mem, 0, MEM_NUM());
    return MEM_SIZE() - 4 - MEM_NUM() * 2 - offset;
}

/**
  * @brief  TSS内存初始化
  * @param  mem   管理内存的首地址
  * @param  size  内存的大小,最大支持到65535
  * @retval 返回成功或者失败
  * @note   需提供给列表一块全局内存空间
  *         本模块会在给定的内存空间内操作数据
  */
int8_t TSS_MemInit(void *mem, uint16_t size)
{
    if (size < 8)
        return TSS_MEMSIZE;
    memset(mem, 0, size);
    MEM_SIZE() = size;
    return TSS_OK;
}

/**
  * @brief  TSS内存申请
  * @param  mem   管理内存的首地址
  * @param  size  申请的内存大小
  * @retval 返回申请的内存首地址
  * @note   无
  */
void *TSS_MemMalloc(void *mem, uint16_t size)
{
    if (MEM_SPACE(mem) < size + 2)
        return NULL;
    void *p = MEM_DATA(mem, MEM_NUM());
    MEM_LEN(MEM_NUM()) = size;
    MEM_NUM() += 1;
    return p;
}

/**
  * @brief  TSS内存释放
  * @param  mem   管理内存的首地址
  * @param  p     需要释放的内存首地址
  * @retval 无
  * @note   无
  */
int8_t TSS_MemFree(void *mem, void *p)
{
    if ((p >= mem) && (p < mem + MEM_SIZE()))
    {
        for (uint16_t i = 0; i < MEM_NUM(); i++)
        {
            if (p == MEM_DATA(mem, i))
            {
                memmove(MEM_DATA(mem, i), MEM_DATA(mem, i + 1), MEM_OFFSET(mem, i + 1, MEM_NUM()));
                memmove((void *)(&MEM_MOVE_8(mem, MEM_SIZE() - (MEM_NUM() - 1) * 2)),
                        (void *)(&MEM_MOVE_8(mem, MEM_SIZE() - MEM_NUM() * 2)),
                        (MEM_NUM() - i - 1) * 2);
                MEM_NUM() -= 1;
                return TSS_OK;
            }
        }
    }
    return TSS_NODATA;
}

/**
  * @brief  返回内存中数据个数
  * @param  mem  管理内存的首地址
  * @retval 返回数据个数
  * @note   无
  */
uint16_t TSS_MemSize(void *mem)
{
    return MEM_NUM();
}

/**
  * @brief  返回内存剩余字节数
  * @param  mem  管理内存的首地址
  * @retval 返回内存剩余字节数
  * @note   无
  */
int32_t TSS_MemSpace(void *mem)
{
    return MEM_SPACE(mem);
}
